package org.go.log.impl;

import org.go.log.Log;
import org.go.log.LogAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.spi.LocationAwareLogger;

/**
 * 
 * @author hejie
 *
 */
public class Log4jAdapter implements LogAdapter {

	static class Slf4JLog extends AbstractLog {
		private static final String FQCN = Slf4JLog.class.getName();
		private LocationAwareLogger locationAwareLogger;
		protected Logger slf4jLogger;

		public Slf4JLog(String name) {
			slf4jLogger = LoggerFactory.getLogger(name);
			if (slf4jLogger instanceof LocationAwareLogger) {
				locationAwareLogger = (LocationAwareLogger) slf4jLogger;
			}
			isDebugEnabled = slf4jLogger.isDebugEnabled();
			isInfoEnabled = slf4jLogger.isInfoEnabled();
			isWarnEnabled = slf4jLogger.isWarnEnabled();
			isErrorEnabled = slf4jLogger.isErrorEnabled();
			isFatalEnabled = slf4jLogger.isErrorEnabled();
		}

		@Override
		protected void log(int level, Object message, Throwable t) {
			String m = String.valueOf(message);
			if (locationAwareLogger != null) {
				locationAwareLogger.log(null, FQCN, level, m, null, t);
			} else {
				switch (level) {
				case LocationAwareLogger.TRACE_INT:
					slf4jLogger.trace(m, t);
					break;
				case LocationAwareLogger.DEBUG_INT:
					slf4jLogger.debug(m, t);
					break;
				case LocationAwareLogger.INFO_INT:
					slf4jLogger.info(m, t);
					break;
				case LocationAwareLogger.WARN_INT:
					slf4jLogger.warn(m, t);
					break;
				case LocationAwareLogger.ERROR_INT:
					slf4jLogger.error(m, t);
					break;
				case LEVEL_FATAL:
					slf4jLogger.error(m, t);
					break;
				}
			}
		}

		@Override
		public void debug(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.DEBUG_INT, message, t);
		}

		@Override
		public void debug(String paramString) {
			slf4jLogger.debug(paramString);
		}

		@Override
		public void debug(String paramString, Object paramObject) {
			slf4jLogger.debug(paramString, paramObject);
		}

		@Override
		public void debug(String paramString, Object paramObject1, Object paramObject2) {
			slf4jLogger.debug(paramString, paramObject1, paramObject2);
		}

		@Override
		public void debug(String paramString, Object[] paramArrayOfObject) {
			slf4jLogger.debug(paramString, paramArrayOfObject);
		}

		/*
		 * (non-Javadoc)
		 * @see org.go.log.Log#debug(java.lang.String, java.lang.Throwable)
		 */
		@Override
		public void debug(String paramString, Throwable paramThrowable) {
			slf4jLogger.debug(paramString, paramThrowable);
		}

		@Override
		public void error(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.ERROR_INT, message, t);
		}

		@Override
		public void error(String paramString) {
			slf4jLogger.error(paramString);
		}

		@Override
		public void error(String paramString, Object paramObject) {
			slf4jLogger.error(paramString, paramObject);
		}

		@Override
		public void error(String paramString, Object paramObject1, Object paramObject2) {
			slf4jLogger.error(paramString, paramObject1, paramObject2);
		}

		@Override
		public void error(String paramString, Object[] paramArrayOfObject) {
			slf4jLogger.error(paramString, paramArrayOfObject);
		}

		@Override
		public void error(String paramString, Throwable paramThrowable) {
			slf4jLogger.error(paramString, paramThrowable);
		}

		@Override
		public void fatal(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.ERROR_INT, message, t);
		}

		@Override
		public String getName() {
			return slf4jLogger.getName();
		}

		@Override
		public void info(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.INFO_INT, message, t);
		}

		@Override
		public void info(String paramString) {
			slf4jLogger.info(paramString);
		}

		@Override
		public void info(String paramString, Object paramObject) {
			slf4jLogger.info(paramString, paramObject);
		}

		@Override
		public void info(String paramString, Object paramObject1, Object paramObject2) {
			slf4jLogger.info(paramString, paramObject1, paramObject2);
		}

		@Override
		public void info(String paramString, Object[] paramArrayOfObject) {
			slf4jLogger.info(paramString, paramArrayOfObject);
		}

		@Override
		public void info(String paramString, Throwable paramThrowable) {
			slf4jLogger.info(paramString, paramThrowable);
		}

		@Override
		public void trace(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.TRACE_INT, message, t);
		}

		@Override
		public void trace(String paramString) {
			slf4jLogger.trace(paramString);
		}

		@Override
		public void trace(String paramString, Object paramObject) {
			slf4jLogger.trace(paramString, paramObject);
		}

		@Override
		public void trace(String paramString, Object paramObject1, Object paramObject2) {
			slf4jLogger.trace(paramString, paramObject1, paramObject2);
		}

		@Override
		public void trace(String paramString, Object[] paramArrayOfObject) {
			slf4jLogger.trace(paramString, paramArrayOfObject);
		}

		@Override
		public void trace(String paramString, Throwable paramThrowable) {
			slf4jLogger.trace(paramString, paramThrowable);
		}

		@Override
		public void warn(Object message, Throwable t) {
			if (isFatalEnabled())
				log(LocationAwareLogger.WARN_INT, message, t);
		}

		@Override
		public void warn(String paramString) {
			slf4jLogger.warn(paramString);
		}

		@Override
		public void warn(String paramString, Object paramObject) {
			slf4jLogger.warn(paramString, paramObject);
		}

		@Override
		public void warn(String paramString, Object paramObject1, Object paramObject2) {
			slf4jLogger.warn(paramString, paramObject1, paramObject2);
		}

		@Override
		public void warn(String paramString, Object[] paramArrayOfObject) {
			slf4jLogger.warn(paramString, paramArrayOfObject);
		}

		@Override
		public void warn(String paramString, Throwable paramThrowable) {
			slf4jLogger.warn(paramString, paramThrowable);
		}
	}

	public boolean canWork() {
		try {
			Class.forName("org.apache.log4j.Logger", false, Thread.currentThread().getContextClassLoader());
			return true;
		} catch (Throwable e) {
		}
		return false;
	}

	@Override
	public Log getLogger(String className) {
		return new Slf4JLog(className);
	}
}
